#pragma once

#include <string>
#include <set>
#include "MyConstants.h"
#include "Strategy.h"

using namespace model;
using namespace std;

struct Point
{
	int x, y;
	Point () {}
	Point (int X, int Y)
	{
		x = X;
		y = Y;
	}
	bool operator == (const Point& p) const;
	bool operator != (const Point& p) const;
	Point& operator = (const Point& p);
	bool operator < (const Point& p) const;
	bool operator <= (const Point& p) const;
	string ToString () const;
};

struct Target
{
	Point location;
	TargetType type;
	TargetSubtype subtype;
	int lastSeen;
	TrooperType authorType;
	int lockedUntil;
	TrooperType lockedBy;

	Target (const Point& Location, int moveIdx, TargetSubtype Subtype, TrooperType AuthorType, int LockedUntil, TrooperType LockedBy);
	Target (const Target& t);
	bool operator == (const Target& other) const;
	bool operator != (const Target& other) const;

	string ToString () const;
};

struct BFSStep
{
	Point location;
	int prevCellIndex;
	int distance;

	BFSStep (const Point& loc, int prev, int d) :
	location (loc), prevCellIndex (prev), distance (d) {}
};

struct BlockSignal
{
	TrooperType assigneeType;
	TrooperType authorType;
	vector<Point> blockedPath;
	int blockedTeamSize;

	BlockSignal ()
		: assigneeType (UNKNOWN_TROOPER), authorType (UNKNOWN_TROOPER), blockedPath (vector<Point> ()), blockedTeamSize (1) {}

	BlockSignal (TrooperType assignee_type, TrooperType author_type, const vector<Point>& BlockedPath, int BlockedTeamSize = 1)
		: assigneeType (assignee_type), authorType (author_type), blockedPath (BlockedPath), blockedTeamSize (BlockedTeamSize) {}

	string ToString ();
};

struct PresetAction
{
	ActionType action;
	int x, y;

	PresetAction () : action (END_TURN), x (0), y (0) {}
	PresetAction (ActionType Action, int X = 0, int Y = 0)
		: action (Action), x (X), y (Y) {}
	string ToString ();
};

struct OneMoveDirective
{
	vector<PresetAction> actions;
	int next;
	int moveIdx;
	Point enemyTargetToRemove;

	OneMoveDirective (int MoveIdx) : next (0), moveIdx (MoveIdx), enemyTargetToRemove (Point (-1, -1)) {}
	string ToString ();
	OneMoveDirective& operator = (const OneMoveDirective& d);
	void Clear ();
};

struct SeenCells
{
	set<Point> cells;
	int moveIdx;
	TrooperType viewer;

	SeenCells () : moveIdx (0), viewer (UNKNOWN_TROOPER) {}
};